#ifndef __H_PATH__
#define __H_PATH__

#include "tstring.h"

namespace bl{

	class WindowsPathSeperator
	{
	public:
		static const tchar DirectorySeparator = TEXT('\\');
		static const tchar VolumeSeparatorChar  = TEXT(':');
	};

	class UnixPathSeperator
	{
	public:
		static const tchar DirectorySeparator = TEXT('/');
		static const tchar VolumeSeparatorChar  = TEXT('/');
	};

	template< typename Seperator = WindowsPathSeperator>
	class tPath
	{
	public:
		tPath(const tchar* path)
		{
			if(path != 0)
				path_ = path;
		}

		tPath(const tstring& path)
		{
			path_ = path;
		}

		tPath(const tPath<Seperator>& path)
		{
			path_ = path.path_;
		}

		tPath& Combine(const tPath<Seperator>& path)
		{
			if(path.path_.empty())
				return *this;
			else if(path_.empty())
				path_ = path.path_;
			else 
			{
				bool firstHasSep = (path_.at(path_.size()-1) == Seperator::DirectorySeparator);
				bool secondHasSep = (path.path_.at(0) == Seperator::DirectorySeparator);
				if(firstHasSep && secondHasSep)
				{
					path_.append(path.path_.begin()+1, path.path_.end());
				}
				else if( firstHasSep || secondHasSep )
				{
					path_.append(path.path_);
				}
				else
				{
					path_.push_back(Seperator::DirectorySeparator);
					path_.append(path.path_);
				}
			}
			return *this;
		}

		tstring GetFileName() const
		{
			if(path_.empty() || (path_.at(path_.size()-1)==Seperator::VolumeSeparatorChar) )
				return tstring();

			tstring::size_type sepPos = path_.rfind(Seperator::DirectorySeparator);
			if(sepPos != tstring::npos)
			{
				return path_.substr(sepPos+1);
			}
			else
			{
				return path_;
			}
		}

		tstring GetFileNameWithoutExtension() const
		{
			tstring fileName = GetFileName();
			tstring::size_type dotPos = fileName.rfind(TEXT('.'));
			if(dotPos != tstring::npos)
				return fileName.substr(0, dotPos);
			else
				return fileName;
		}

		tstring GetExtension() const
		{
			tstring::size_type dotPos = path_.rfind(TEXT('.'));
			if(dotPos != tstring::npos)
				return path_.substr(dotPos+1);
			return tstring();
		}

		tstring GetParent() const
		{
			if(path_.empty())
				return tstring();

			tstring::size_type spPos = path_.rfind(Seperator::DirectorySeparator);
			if(spPos == tstring::npos)	// Didn't find a separator
				return tstring();
			else if(spPos == path_.size()-1)	// The last character is separator
				spPos = path_.rfind(Seperator::DirectorySeparator, spPos-1);

			return path_.substr(0, spPos+1);
		}

		const tPath& ChangeExtension(const tstring& ext)
		{
			if(!path_.empty())
			{
				tstring::size_type dotPos = path_.rfind(TEXT('.'));
				if(ext.empty())		// Remove the extension
				{
					if(dotPos != tstring::npos)
						path_.erase(dotPos);	// An extension exist, so erase it
				}
				else	// Change the extension
				{
					tstring::size_type seperatorPos = path_.rfind(Seperator::DirectorySeparator);
					if(dotPos != tstring::npos && ( (seperatorPos==tstring::npos) || (dotPos>seperatorPos) ) )	// Replace the old one
						path_.replace(dotPos+1, path_.size(), ext);
					else
					{	// No extension exist, just append a new extension
						path_.push_back(_T('.'));
						path_.append(ext);
					}
				}
			}
			return *this;
		}

		const tstring& ToString() const
		{
			return path_;
		}

		operator const tchar*() const
		{
			return path_.c_str();
		}

	private:
		tstring path_;
	};

	typedef tPath<> Path;

}

#endif